package com.pg.agent.engine.service.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pg.agent.engine.client.model.ComponentOutParam;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class JSONUtils {
    public static Map<String, Object> flattenJson(JSONObject jsonObject) {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode node = null;
        try {
            node = objectMapper.readTree(jsonObject.toJSONString());
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        Map<String, Object> result = new HashMap<>();

        if (!node.isObject()) {
            return result; // Only process objects
        }

        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> field = fields.next();

            List<String> keys = new LinkedList<>();
            keys.add(field.getKey());

            addFieldValue(result, keys, field.getValue(), null);
        }

        return result;
    }

    private static void addFieldValue(Map<String, Object> result, List<String> keys, JsonNode value, String separator) {
        StringBuilder keyBuilder = new StringBuilder();
        for (int i = 0; i < keys.size(); i++) {
            keyBuilder.append((i > 0 && separator != null ? separator : "")).append(keys.get(i));
        }

        if (value == null || value.isNull()) {
            result.put(keyBuilder.toString(), null);
        } else if (value.isObject()) {
            Iterator<Map.Entry<String, JsonNode>> subFields = value.fields();
            while (subFields.hasNext()) {
                Map.Entry<String, JsonNode> subField = subFields.next();

                List<String> subKeys = new LinkedList<>(keys);
                subKeys.add(subField.getKey());

                addFieldValue(result, subKeys, subField.getValue(), separator);
            }
            result.put(keyBuilder.toString(), JSONObject.parseObject(value.toString()));
        } else {
            if (value.isInt() || value.isLong()) {
                result.put(keyBuilder.toString(), value.intValue());
            } else if (value.isLong()) {
                result.put(keyBuilder.toString(), value.longValue());
            } else if (value.isArray()) {
                List<String> strings = new ArrayList<>();
                for (JsonNode element : value) {
                    strings.add(element.textValue());
                }
                result.put(keyBuilder.toString(), strings);
            } else {
                result.put(keyBuilder.toString(), value.textValue());
            }

        }
    }

    public static void flattenJson(String prefix, JSONObject obj, Map<String, Object> flattenedMap) {
        if (obj == null) {
            return;
        }
        for (String key : obj.keySet()) {
            Object value = obj.get(key);
            if (value instanceof JSONObject) {
                if (!flattenedMap.containsKey(key)) {
                    flattenedMap.put(prefix + key, value);
                }
                flattenJson(prefix + key, (JSONObject) value, flattenedMap);
            } else {
                flattenedMap.put(prefix + key, value);
            }
        }
    }

    public static void getAllComponentOutParam(List<ComponentOutParam> list, List<ComponentOutParam> all, String paramCode) {
        if (!CollectionUtil.isEmpty(list)) {
            for (ComponentOutParam component : list) {
                String newParamCode = paramCode + component.getNewParamCode();
                component.setNewParamCode(newParamCode);
                getAllComponentOutParam(component.getChildren(), all, newParamCode);
                component.setChildren(null);
                all.add(component);
            }
        }
    }

    public static void main(String[] args) {
        Map<String, Object> flattenedMap = new LinkedHashMap<>();
        String a = "{\"a\": 1,\"b\": \"b\",\"c\": {\"d\": 1},\"e\": [{\"f\": 1},\"1\",1,[{\"a\": 1}]]}";
        JSONObject parse = JSONObject.parseObject(a);
        flattenJson("root", parse, flattenedMap);
        System.out.println(flattenedMap);
    }

}
